
syntax on
filetype indent on
filetype plugin on

call plug#begin('~/.vim/plugged')
    Plug 'clones/vim-genutils'  " 通用函数
    Plug 'Yggdroot/indentLine'  " 缩进线
    Plug 'preservim/nerdtree'
    Plug 'scrooloose/nerdcommenter'  " 注释
    Plug 'jlanzarotta/bufexplorer'   " 缓冲区浏览器
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'luochen1990/rainbow'  " 彩色括号
    Plug 'vim-scripts/taglist.vim'  " 左边标签列表
    Plug 'mhinz/vim-signify', { 'branch': 'legacy' }  "Git,Svn管理
    Plug 'itchyny/lightline.vim'  " 状态栏
    Plug 'vim-scripts/a.vim'  " .h/.c 切换
    Plug 'vim-airline/vim-airline'
call plug#end()
"=========基本配置 ========
let mapleader=" "
" ^z快速进入shell
nmap <C-Z> :shell<cr>
" 判断操作系统
if (has("win32") || has("win64") || has("win32unix"))
    let g:isWin = 1
else
    let g:isWin = 0
endif
" 判断是终端还是gvim
if has("gui_running")
    let g:isGUI = 1
else
    let g:isGUI = 0
endif

" 快捷打开编辑vimrc文件的键盘绑定
map <silent> <leader>ee :e $HOME/.vim/vimrc<cr>
autocmd! bufwritepost *.vimrc source $HOME/.vim/vimrc

set background=dark
colorscheme desert

autocmd BufEnter * :syntax sync fromstart
set nu "显示行号
"将tab键改为两个空格
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set notimeout
set mouse=a
set nocompatible    " 关闭兼容模式
set showcmd         " 显示命令
set lz              " 当运行宏时，在命令执行完成之前，不重绘屏幕
set hid             " 可以在没有保存的情况下切换buffer
set backspace=eol,start,indent
set whichwrap+=<,>,h,l " 退格键和方向键可以换行
set incsearch       " 增量式搜索
set hlsearch        " 高亮搜索

set ignorecase
set smartcase
set magic           " 额，自己:h magic吧，一行很难解释
set showmatch       " 显示匹配的括号
set nobackup        " 关闭备份
set nowb
set noswapfile      " 不使用swp文件，注意，错误退出后无法恢复
set lbr             " 在breakat字符处而不是最后一个字符处断行
set ai              " 自动缩进
set si              " 智能缩进
set autoindent
set cindent         " C/C++风格缩进
set cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>1s,=1s,:1s "设置C/C++语言的具体缩进方式
set linebreak " 整词换行
set ruler " 标尺
set wildmenu
set nofen
set fdl=10
set t_Co=256
set history=100   " vim记住的历史操作的数量，默认的是20
set autoread     " 当文件在外部被修改时，自动重新读取
set encoding=utf8
set fileencodings=utf8,gb2312,gb18030,ucs-bom,latin1
set laststatus=2      " 总是显示状态栏
highlight StatusLine cterm=bold ctermfg=yellow ctermbg=Gray
" 代码折叠
set foldenable
set foldmethod=manual
set foldcolumn=1

"显示优化
"如果行尾有多余的空格(包括 Tab 键),该配置将让这些空格显示成可见的小方块
set listchars=tab:»■,trail:■
set list

"出错时，发出视觉提示，通常是屏幕闪烁
set visualbell

"光标所在的当前行高亮
set cursorline
"highlight CursorLine   cterm=NONE ctermbg=Black ctermfg=Cyan guibg=NONE guifg=NONE
"highlight CocHighlightText cterm=NONE ctermbg=yellow ctermfg=black guibg=NONE guifg=NONE


"设置vim打开文件光标指在上次退出位置
au BufReadPost * if line("'\"") > 0|if line("'\"") <= line("$")|exe("norm '\"")|else|exe "norm $"|endif|endif

" 删除buffer时不关闭窗口
command! Bclose call <SID>BufcloseCloseIt()
function! <SID>BufcloseCloseIt()
let l:currentBufNum = bufnr("%")
let l:alternateBufNum = bufnr("#")
if buflisted(l:alternateBufNum)
    buffer #
else
    bnext
endif
if bufnr("%") == l:currentBufNum
    new
endif
if buflisted(l:currentBufNum)
    execute("bdelete! ".l:currentBufNum)
endif
endfunction

highlight PMenu ctermfg=40 ctermbg=0
highlight PMenuSel ctermfg=0 ctermbg=4

" 根据给定方向搜索当前光标下的单词，结合下面两个绑定使用
function! VisualSearch(direction) range
let l:saved_reg = @"
execute "normal! vgvy"
let l:pattern = escape(@", '\\/.*$^~[]')
let l:pattern = substitute(l:pattern, "\n$", "", "")
if a:direction == 'b'
    execute "normal ?" . l:pattern . "<cr>"
else
    execute "normal /" . l:pattern . "<cr>"
endif
let @/ = l:pattern
let @" = l:saved_reg
endfunction
" 用 */# 向 前/后 搜索光标下的单词
noremap <silent> * :call VisualSearch('f')<CR>
noremap <silent> # :call VisualSearch('b')<CR>
" 在文件名上按gf时，在新的tab中打开

" 用c-j,k在buffer之间切换
nn <C-J> :bn<cr>
nn <C-K> :bp<cr>
nn <C-H> :b1<cr>

"缩写
iab idate <c-r>=strftime("%Y-%m-%d")<CR>
iab itime <c-r>=strftime("%H:%M")<CR>
iab idatetime <c-r>=strftime("%Y-%m-%d %H:%M")<CR>
iab iname Chunjun Li
iab imail chunjun.li@aqara.com
iab iauth Chunjun Li <chunjun.li@aqara.com>
iab ifile <C-R>=expand("%:t")<CR>
let s:PlugWinSize = 30


"快捷操作
nnoremap s <nop>
nnoremap Q :q<CR>
nnoremap S :w<CR>
nnoremap R :source $MYVIMRC<CR>

nnoremap - Nzz
nnoremap = nzz

inoremap jj <ESC>

"======基本配置 END==========

"配置Taglist
nmap <silent> <leader>t :TlistToggle<cr>
" let g:showfuncctagsbin = '/home/lichunjun/bin/ctags'
let Tlist_Show_One_File = 0
let Tlist_Exit_OnlyWindow = 1
let Tlist_Use_Right_Window = 0
let Tlist_File_Fold_Auto_Close = 1
let Tlist_GainFocus_On_ToggleOpen = 0
let Tlist_WinWidth = s:PlugWinSize
let Tlist_Auto_Open = 0
let Tlist_Display_Prototype = 0
"let Tlist_Close_On_Select = 1

"配置NERD_commenter.vim
" http://www.vim.org/scripts/script.php?script_id=1218
" Toggle单行注释/“性感”注释/注释到行尾/取消注释
map <leader>cc ,c<space>
map <leader>cs ,cs
map <leader>c$ ,c$
map <leader>cu ,cu
"======NERD_commenter END======

"配置nerdtree
let NERDTreeShowHidden = 1
let NERDTreeWinSize = s:PlugWinSize
nnoremap <F3> :NERDTreeToggle<CR>
"=====NERDTree END========

"配置Buffers Explorer 需要genutils.vim
" http://vim.sourceforge.net/scripts/script.php?script_id=42
" http://www.vim.org/scripts/script.php?script_id=197
let g:bufExplorerDefaultHelp=0       " Do not show default help.
let g:bufExplorerShowRelativePath=1  " Show relative paths.
let g:bufExplorerSortBy='mru'        " Sort by most recently used.
let g:bufExplorerSplitRight=0        " Split left.
let g:bufExplorerSplitVertical=1     " Split vertically.
let g:bufExplorerSplitVertSize = s:PlugWinSize  " Split width
let g:bufExplorerUseCurrentWindow=1  " Open in new window.
autocmd BufWinEnter \[Buf\ List\] setl nonumber
nmap <silent> <leader>b :BufExplorer<CR>
"======Buffers Explorer END====== 

"配置multi language
set termencoding=utf-8
"======multi language END======

"配置indentLine
let g:indentLine_enabled = 1
let g:indent_guides_guide_size = 1  " 指定对齐线的尺寸
let g:indent_guides_start_level = 2  " 从第二层开始可视化显示缩进
"======indentLine END======

"配置Rainbow
let g:rainbow_active = 1
let g:rainbow_conf = {
\   'guifgs': ['darkorange3', 'seagreen3', 'royalblue3', 'firebrick'],
\   'ctermfgs': ['lightyellow', 'lightred','lightblue', 'lightmagenta'],
\   'operators': '_,_',
\   'parentheses': ['start=/(/ end=/)/ fold', 'start=/\[/ end=/\]/ fold', 'start=/{/ end=/}/ fold'],
\   'separately': {
\       '*': {},
\       'tex': {
\           'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/'],
\       },
\       'lisp': {
\           'guifgs': ['darkorange3', 'seagreen3', 'royalblue3', 'firebrick'],
\       },
\       'vim': {
\           'parentheses': ['start=/(/ end=/)/', 'start=/\[/ end=/\]/', 'start=/{/ end=/}/ fold', 'start=/(/ end=/)/ containedin=vimFuncBody', 'start=/\[/ end=/\]/ containedin=vimFuncBody', 'start=/{/ end=/}/ fold containedin=vimFuncBody'],
\       },
\       'html': {
\           'parentheses': ['start=/\v\<((area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)[ >])@!\z([-_:a-zA-Z0-9]+)(\s+[-_:a-zA-Z0-9]+(\=("[^"]*"|'."'".'[^'."'".']*'."'".'|[^ '."'".'"><=`]*))?)*\>/ end=#</\z1># fold'],
\       },
\       'css': 0,
\   }
\}
"======Rainbowi END======

"配置lightline.vim
let g:lightline = { 'colorscheme': 'wombat' }
"======lightline.vim END======


"配置coc
" coc extensions
let g:coc_global_extensions = [
      \ 'coc-json',
      \ 'coc-tsserver',
      \ 'coc-css',
      \ 'coc-html',
      \ 'coc-vimlsp',
      \ 'coc-cmake',
      \ 'coc-highlight',
      \ 'coc-pyright'
      \ ]
" 上面的配置在重新进入init.vim时会自动安装coc的语言服务器（可能需要多次进入init.vim才能完全下载成功），但是也可以通过CocInstall安装语言服务器，如:CocInstall coc-pyright
" 其他的语言服务器，可参考：https://github.com/neoclide/coc.nvim/wiki/Language-servers

set signcolumn=number " 在行号的位置提醒错误
" 配置tab和shift tab对候选词进行选取
" <TAB> to select candidate forward or
" pump completion candidate
" 使用tab键向下选择自动补全的候选词
inoremap <silent><expr> <TAB>
      \ coc#pum#visible() ? coc#pum#next(1) :
      \ CheckBackspace() ? "\<Tab>" :
      \ coc#refresh()
" <s-TAB> to select candidate backward
" 使用shift+tab向上选择自动补全的候选词
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u breaks current undo, please make your own choice.
" 按回车键确认我们所选择的候选词
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
                              \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"

function! CheckBackspace() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction

" 使用K来跳转到帮助文档，如将光标定位到nnoremap，然后使用K可进行跳转
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
  if(index(['vim', 'help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  elseif (coc#rpc#ready())
    call CocActionAsync('doHover')
  else
    execute '!' . &keywordprg . " " . expand('<cword>')
  endif
endfunction
" 重命名，重命名一个，其他与此同名的，也会被重命名
nmap <leader>rn <Plug>(coc-rename)
" 格式化配置，具体可参考coc的github网站。
xmap <leader>f <Plug>(coc-format-selected)

augroup mygroup
  autocmd!
  autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
  autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end

" diagnostic info 错误提示信息
" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <LEADER>a  :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <LEADER>e  :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <LEADER>c  :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <LEADER>o  :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <LEADER>s  :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <LEADER>j  :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <LEADER>k  :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <LEADER>p  :<C-u>CocListResume<CR>


" Remap <C-f> and <C-b> for scroll float windows/popups. 滚动浮窗
if has('nvim-0.4.0') || has('patch-8.2.0750')
  nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
  nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
  inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<C-r>=coc#float#scroll(1)\<CR>" : "\<Right>"
  inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<C-r>=coc#float#scroll(0)\<CR>" : "\<Left>"
  vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
  vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
endif

" statusline support
" set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}  "TODO

" GoTo code navigation. 代码的跳转，包括跳转到定义、跳转到实现等
"nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gd :tab sp<CR><Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)

" 使用nvim编辑cpp文件，然后输入:Gcmake后，就会调用下面函数，此函数判断当前目录下是否有CMakeLists.txt文件，
" 如果有的话，就在当前目录的.vscode目录下生成compile_commands.json。

function! s:generate_compile_commands()
  if empty(glob('CMakeLists.txt'))
    echo "Can't find CMakeLists.txt"
    return
  endif
  if empty(glob('.vscode'))
    execute 'silent !mkdir .vscode'
  endif
  execute '!cmake -DCMAKE_BUILD_TYPE=debug
      \ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -S . -B .vscode'
endfunction
command! -nargs=0 Gcmake :call s:generate_compile_commands()

" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap ;a  <Plug>(coc-codeaction-selected)
nmap ;a  <Plug>(coc-codeaction-selected)

" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac  <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf  <Plug>(coc-fix-current)

" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)

" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of language server.
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)

" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocAction('format')

" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call     CocAction('fold', <f-args>)

" Add `:OR` command for organize imports of the current buffer.
command! -nargs=0 OR   :call     CocAction('runCommand', 'editor.action.organizeImport')

" Add (Neo)Vim's native statusline support.
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline.
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}

"===========Coc END================

